// src-tauri/src/main.rs

use tauri::{State};
use serde::{Deserialize, Serialize};
use rusqlite::{params, Connection, Result as SqlResult};
use std::sync::Mutex;
use dirs_next::data_dir;
use std::path::PathBuf;

// -------------------------------
// 数据结构定义
// -------------------------------

#[derive(Serialize, Deserialize, Debug)]
pub struct Todo {
    pub id: i64,
    pub text: String,
    pub completed: bool,
    pub deleted: bool,
    pub created_at: String,
    pub completed_at: Option<String>,
    pub updated_at: String,
}

#[derive(Serialize, Deserialize)]
pub struct TodoStats {
    pub total: i64,
    pub completed: i64,
    pub active: i64,
}

#[derive(Deserialize)]
pub struct UpdateTodoPayload {
    pub id: i64,
    pub completed: bool,
}

#[derive(Deserialize)]
pub struct SearchFilter {
    pub search: Option<String>,
    pub filter: Option<String>, // "all", "active", "completed"
}

// -------------------------------
// 数据库操作封装
// -------------------------------

struct DbConnection(Mutex<Connection>);

impl DbConnection {
    fn new(path: PathBuf) -> Result<Self, rusqlite::Error> {
        let conn = Connection::open(&path)?;
        conn.pragma_update(None, "journal_mode", "WAL")?;

        // 创建表
        conn.execute(
            "CREATE TABLE IF NOT EXISTS todos (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                text TEXT NOT NULL,
                completed INTEGER NOT NULL DEFAULT 0,
                deleted INTEGER NOT NULL DEFAULT 0,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                completed_at DATETIME,
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
            )",
            [],
        )?;

        // 为现有数据添加 deleted 列（如果不存在）
        let _ = conn.execute(
            "ALTER TABLE todos ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0",
            [],
        );

        Ok(DbConnection(Mutex::new(conn)))
    }
}

// -------------------------------
// Tauri 命令函数
// -------------------------------

#[tauri::command]
fn get_todos(db: State<DbConnection>, search_filter: SearchFilter) -> Result<Vec<Todo>, String> {
    let conn = db.0.lock().map_err(|e| e.to_string())?;
    let mut stmt = match (search_filter.search.as_deref(), search_filter.filter.as_deref()) {
        (Some(_search), Some("active")) => {
            conn.prepare("SELECT * FROM todos WHERE text LIKE ? AND completed = 0 AND deleted = 0 ORDER BY created_at DESC")
                .map_err(|e| e.to_string())?
        }
        (Some(_search), Some("completed")) => {
            conn.prepare("SELECT * FROM todos WHERE text LIKE ? AND completed = 1 AND deleted = 0 ORDER BY completed_at DESC")
                .map_err(|e| e.to_string())?
        }
        (Some(_search), _) => {
            conn.prepare("SELECT * FROM todos WHERE text LIKE ? AND deleted = 0 ORDER BY created_at DESC")
                .map_err(|e| e.to_string())?
        }
        (None, Some("active")) => {
            conn.prepare("SELECT * FROM todos WHERE completed = 0 AND deleted = 0 ORDER BY created_at DESC")
                .map_err(|e| e.to_string())?
        }
        (None, Some("completed")) => {
            conn.prepare("SELECT * FROM todos WHERE completed = 1 AND deleted = 0 ORDER BY completed_at DESC")
                .map_err(|e| e.to_string())?
        }
        _ => {
            conn.prepare("SELECT * FROM todos WHERE deleted = 0 ORDER BY created_at DESC")
                .map_err(|e| e.to_string())?
        }
    };

    // 修改参数处理逻辑，避免临时值被过早释放
    let search_param: String;
    let params: Vec<&dyn rusqlite::ToSql> = match (search_filter.search.as_deref(), search_filter.filter.as_deref()) {
        (Some(search), _) => {
            search_param = format!("%{}%", search);
            vec![&search_param]
        }
        _ => vec![],
    };

    let rows = stmt
        .query_map(&*params, |row| {
            Ok(Todo {
                id: row.get("id")?,
                text: row.get("text")?,
                completed: row.get::<_, i32>("completed")? != 0,
                deleted: row.get::<_, i32>("deleted")? != 0,
                created_at: row.get("created_at")?,
                completed_at: row.get("completed_at")?,
                updated_at: row.get("updated_at")?,
            })
        })
        .map_err(|e| e.to_string())?;

    let todos = rows
        .collect::<SqlResult<Vec<Todo>, _>>()
        .map_err(|e| e.to_string())?;

    Ok(todos)
}

#[tauri::command]
fn create_todo(db: State<DbConnection>, text: String) -> Result<Todo, String> {
    let text = text.trim();
    if text.is_empty() {
        return Err("任务内容不能为空".to_string());
    }

    let conn = db.0.lock().map_err(|e| e.to_string())?;

    conn.execute(
        "INSERT INTO todos (text, completed, deleted, created_at, updated_at) VALUES (?, 0, 0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)",
        &[text],
    )
    .map_err(|e| e.to_string())?;

    let id = conn.last_insert_rowid();

    let mut stmt = conn
        .prepare("SELECT * FROM todos WHERE id = ?")
        .map_err(|e| e.to_string())?;
    let todo = stmt
        .query_row(&[&id], |row| {
            Ok(Todo {
                id: row.get("id")?,
                text: row.get("text")?,
                completed: row.get::<_, i32>("completed")? != 0,
                deleted: row.get::<_, i32>("deleted")? != 0,
                created_at: row.get("created_at")?,
                completed_at: row.get("completed_at")?,
                updated_at: row.get("updated_at")?,
            })
        })
        .map_err(|e| e.to_string())?;

    Ok(todo)
}

#[tauri::command]
fn update_todo_status(
    db: State<DbConnection>,
    payload: UpdateTodoPayload,
) -> Result<Todo, String> {
    let conn = db.0.lock().map_err(|e| e.to_string())?;

    let (sql, params) = if payload.completed {
        (
            "UPDATE todos SET completed = ?, completed_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
            params![payload.completed as i32, payload.id]
        )
    } else {
        (
            "UPDATE todos SET completed = ?, completed_at = NULL, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
            params![payload.completed as i32, payload.id]
        )
    };

    let result = conn.execute(sql, params).map_err(|e| e.to_string())?;

    if result == 0 {
        return Err("任务不存在".to_string());
    }

    let mut stmt = conn
        .prepare("SELECT * FROM todos WHERE id = ?")
        .map_err(|e| e.to_string())?;
    let todo = stmt
        .query_row(&[&payload.id], |row| {
            Ok(Todo {
                id: row.get("id")?,
                text: row.get("text")?,
                completed: row.get::<_, i32>("completed")? != 0,
                deleted: row.get::<_, i32>("deleted")? != 0,
                created_at: row.get("created_at")?,
                completed_at: row.get("completed_at")?,
                updated_at: row.get("updated_at")?,
            })
        })
        .map_err(|e| e.to_string())?;

    Ok(todo)
}

#[tauri::command]
fn delete_todo(db: State<DbConnection>, id: i64) -> Result<(), String> {
    let conn = db.0.lock().map_err(|e| e.to_string())?;
    let result = conn
        .execute("UPDATE todos SET deleted = 1, updated_at = CURRENT_TIMESTAMP WHERE id = ? AND deleted = 0", [id])
        .map_err(|e| e.to_string())?;

    if result == 0 {
        return Err("任务不存在或已被删除".to_string());
    }

    Ok(())
}

#[tauri::command]
fn delete_completed_todos(db: State<DbConnection>) -> Result<usize, String> {
    let conn = db.0.lock().map_err(|e| e.to_string())?;
    let result = conn
        .execute("UPDATE todos SET deleted = 1, updated_at = CURRENT_TIMESTAMP WHERE completed = 1 AND deleted = 0", [])
        .map_err(|e| e.to_string())?;

    Ok(result)
}

#[tauri::command]
fn get_stats(db: State<DbConnection>) -> Result<TodoStats, String> {
    let conn = db.0.lock().map_err(|e| e.to_string())?;
    let mut stmt = conn
        .prepare(
            "SELECT 
                COUNT(*) as total,
                SUM(CASE WHEN completed = 1 THEN 1 ELSE 0 END) as completed,
                SUM(CASE WHEN completed = 0 THEN 1 ELSE 0 END) as active
            FROM todos WHERE deleted = 0",
        )
        .map_err(|e| e.to_string())?;

    let stats = stmt
        .query_row(
            [], 
        |row| {
            Ok(TodoStats {
                total: row.get("total")?,
                completed: row.get("completed")?,
                active: row.get("active")?,
            })
        })
        .map_err(|e| e.to_string())?;

    Ok(stats)
}

// -------------------------------
// 主函数
// -------------------------------

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    // 构建数据库路径
    let mut db_path = data_dir().unwrap_or_else(|| std::env::current_dir().unwrap());
    db_path.push("todo-app"); // 比如 "todo-app"
    std::fs::create_dir_all(&db_path).expect("无法创建数据目录");
    db_path.push("todos.db");

    println!("数据库路径: {:?}", db_path);

    // 初始化数据库
    let db = DbConnection::new(db_path).expect("无法打开数据库");

    tauri::Builder::default()
        .manage(db)
        .invoke_handler(tauri::generate_handler![
            get_todos,
            create_todo,
            update_todo_status,
            delete_todo,
            delete_completed_todos,
            get_stats
        ])
        .run(tauri::generate_context!())
        .expect("应用启动失败");
}

// #[cfg_attr(mobile, tauri::mobile_entry_point)]
// pub fn run() {
//     tauri::Builder::default()
//         .invoke_handler(tauri::generate_handler![
//             commands::greet,
//         ])
//         .run(tauri::generate_context!())
//         .expect("error while running tauri application");
// }
